/*
 * Copyright (C) 2010 Tetsuya Yasuda <tetsuyayasuda@gmail.com>
 */
package jp.tyas.libs.terminal;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Hashtable;

public class BaseTerminal extends TerminalBuffer implements Terminal, Terminal.Connection
{
  Hashtable props = null;
  PipedInputStream  clientIn = null, termIn = null;
  PipedOutputStream clientOut = null, termOut = null;
  Thread receiver = null;
  
  public BaseTerminal(int max) {
    this(max, null);
  }

  public BaseTerminal(int max, Hashtable props) {
    super(max);
    this.props = props == null ? new Hashtable(): new Hashtable(props);
  }

  public Terminal.Connection openConnection() {
    if (receiver != null)
      return null;

    this.termIn  = new PipedInputStream();
    this.termOut = new PipedOutputStream();

    try {
      this.clientIn  = new PipedInputStream(termOut);
      this.clientOut = new PipedOutputStream(termIn);
    } catch (IOException e) { /* should not come here */ }

    receiver = new Thread() {
        public void run() {
          while (!isInterrupted()) {
            try {
              putCharOut((char) termIn.read());
            } catch (IOException e) {
              e.printStackTrace();
            }
          }
          System.out.println("hello");
        }
      };
    receiver.start();
    return this;
  }

  public String putCharIn(char c) {
    String ret = super.putCharIn(c);
    if (ret != null)
      try {
        termOut.write((ret + "\n").getBytes());
      } catch (IOException e) {
        e.printStackTrace();
      }
    return ret;
  }

  public void putStringIn(CharSequence cs) {
    int len = cs.length();
    for (int i = 0; i < len; i++)
      this.putCharIn(cs.charAt(i));
  }

  public boolean setProperty (String key, Object val) {
    props.put(key, val);
    return true;
  }

  public Object getProperty (String key) {
    return props.get(key);
  }

  public InputStream getInputStream() {
    return clientIn;
  }

  public OutputStream getOutputStream() {
    return clientOut;
  }

  public InputStream getTermInputStream() {
    return termIn;
  }

  public OutputStream getTermOutputStream() {
    return termOut;
  }

  public void close() {
    try {
      receiver.interrupt();
      clientIn.close();
      clientOut.close();
      termOut.close();
      termIn.close();

      receiver = null;
      clientIn = termIn = null;
      clientOut = termOut = null;
    } catch (IOException e) {}
  }
}
